#include <linux/linkage.h>
#include <asm-i386/ptrace.h>
#include <asm-i386/stdio.h>
#include <asm-i386/io.h>
/*
 * do_IRQ handles all normal device IRQ's (the special
 * SMP cross-CPU interrupts have their own specific
 * handlers).
 */
asmlinkage unsigned int do_IRQ(struct pt_regs regs)
{
    /*
     * We ack quickly, we don't want the irq controller
     * thinking we're snobs just because some other CPU has
     * disabled global interrupts (we have already done the
     * INT_ACK cycles, it's too late to try to pretend to the
     * controller that we aren't taking the interrupt).
     *
     * 0 return value means that this irq is already being
     * handled by some other CPU. (or is disabled)
     */
    int i=0;
    i++;
    printk("dong...dong...\n");
    int w=0;
    w++;
//    int irq = regs.orig_eax & 0xff; /* high bits used in ret_from_ code  */
//    int cpu = 0;
//    irq_desc_t *desc = irq_desc + irq;
//    struct irqaction * action;
//    unsigned int status;
//
//
//    kstat.irqs[cpu][irq]++;
//    spin_lock(&desc->lock);
//    desc->handler->ack(irq);
//    /*
//       REPLAY is when Linux resends an IRQ that was dropped earlier
//       WAITING is used by probe to mark irqs that are being tested
//       */
//    status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
//    status |= IRQ_PENDING; /* we _want_ to handle it */
//
//    /*
//     * If the IRQ is disabled for whatever reason, we cannot
//     * use the action we have.
//     */
//    action = NULL;
//    if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
//        action = desc->action;
//        status &= ~IRQ_PENDING; /* we commit to handling */
//        status |= IRQ_INPROGRESS; /* we are handling it */
//    }
//    desc->status = status;
//
//    /*
//     * If there is no IRQ handler or it was disabled, exit early.
//       Since we set PENDING, if another processor is handling
//       a different instance of this same irq, the other processor
//       will take care of it.
//     */
//    if (!action)
//        goto out;
//
//    /*
//     * Edge triggered interrupts need to remember
//     * pending events.
//     * This applies to any hw interrupts that allow a second
//     * instance of the same irq to arrive while we are in do_IRQ
//     * or in the handler. But the code here only handles the _second_
//     * instance of the irq, not the third or fourth. So it is mostly
//     * useful for irq hardware that does not mask cleanly in an
//     * SMP environment.
//     */
//    for (;;) {
//        spin_unlock(&desc->lock);
//        handle_IRQ_event(irq, &regs, action);
//        spin_lock(&desc->lock);
//
//        if (!(desc->status & IRQ_PENDING))
//            break;
//        desc->status &= ~IRQ_PENDING;
//    }
//    desc->status &= ~IRQ_INPROGRESS;
//    out:
//    /*
//     * The ->end() handler has to deal with interrupts which got
//     * disabled while the handler was running.
//     */
//    desc->handler->end(irq);
//    spin_unlock(&desc->lock);
    outb(0xa0, 0x20);
    outb(0x20, 0x20);
    return 1;
}
